﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Xml;
using System.Runtime.InteropServices;

using SuperMapLib;

namespace SDB2DM.SpatialType
{
    class Curve : Spatial
    {
        #region 定数
        public const string ID_PREFIX = Utility.SPATIAL_ID_PREFIX_CURVE;
        private const string ORIENTATION_TAG = Utility.SPATIAL_ORIENTATION_TAG;
        private const string ORIENTATION_VALUE = Utility.SPATIAL_ORIENTATION_VALUE;
        private const string PRIMITIVE_TAG = Utility.SPATIAL_PRIMITIVE_TAG;
        private const string SEGMENT_TAG = Utility.SPATIAL_SEGMENT_TAG;
        private const string LINESTRING_TAG = Utility.SPATIAL_LINESTRING_TAG;
        private const string INTERPOLATION_VALUE = Utility.SPATIAL_INTERPOLATION_VALUE;
        private const string INTERPOLATION_TAG = Utility.SPATIAL_INTERPOLATION_TAG;
        private const string CONTROLPOINT_TAG = Utility.SPATIAL_CONTROLPOINT_TAG;
        private const string POINTARRAY_TAG = Utility.SPATIAL_POINTARRAY_TAG;
        private const string ARRAYCOLUMN_TAG = Utility.SPATIAL_ARRAY_COLUMN_TAG;
        private const string INDIRECT_TAG = Utility.SPATIAL_INDIRECT_TAG;
        private const string POINTREF_TAG = Utility.SPATIAL_POINTREF_TAG;
        private const string POINTREFPOINT_TAG = Utility.SPATIAL_POINTREFPOINT_TAG;
        #endregion

        public Curve(XmlDocument XMLDoc, XmlNode objectNode, string strFeature)
            : base(XMLDoc, objectNode, strFeature, Spatial.CURVE_TAG)
        {
            //this.XMLDoc = XMLDoc;
            //this.objectNode = objectNode;
            //this.strFeature = strFeature;
        }

        /*
        private string orientationTag = String.Empty;
        public string OrientationTag
        {
            get
            {
                return Utility.SPATIAL_ORIENTATION_TAG;
            }
        }

        private string primitiveTag = String.Empty;
        public string PrimitiveTag
        {
            get
            {
                return Utility.SPATIAL_PRIMITIVE_TAG;
            }
        }
        */

        private string primitiveIdref = String.Empty;
        public string PrimitiveIdref
        {
            get 
            {
                return primitiveIdref;
            }
            set
            {
                primitiveIdref = value;
            }
        }

        /*
        private string segmentTag = String.Empty;
        public string SegmentTag
        {
            get
            {
                return Utility.SPATIAL_SEGMENT_TAG;
            }
        }

        private string lineStringTag = String.Empty;
        public string LineStringTag
        {
            get
            {
                return Utility.SPATIAL_LINESTRING_TAG;
            }
        }

        private string interpolationValue = String.Empty;
        public string LnterpolationValue
        {
            get
            {
                return Utility.SPATIAL_INTERPOLATION_VALUE;
            }
        }

        private string interpolationTag = String.Empty;
        public string InterpolationTag
        {
            get
            {
                return Utility.SPATIAL_INTERPOLATION_TAG;
            }
        }

        private string controlPointTag = String.Empty;
        public string ControlPointTag
        {
            get
            {
                return Utility.SPATIAL_CONTROLPOINT_TAG;
            }
        }

        private string pointArrayTag = String.Empty;
        public string PointArrayTag
        {
            get
            {
                return Utility.SPATIAL_POINTARRAY_TAG;
            }
        }

        private string arrayColumnTag = String.Empty;
        public string ArraycolumnTag
        {
            get
            {
                return Utility.SPATIAL_ARRAY_COLUMN_TAG;
            }
        }

        private string indirectTag = String.Empty;
        public string IndirectTag
        {
            get
            {
                return Utility.SPATIAL_INDIRECT_TAG;
            }
        }

        private string pointRefTag = String.Empty;
        public string PointRefTag
        {
            get
            {
                return Utility.SPATIAL_POINTREF_TAG;
            }
        }

        private string pointRefPointTag = String.Empty;
        public string PointRefPointTag
        {
            get
            {
                return Utility.SPATIAL_POINTREFPOINT_TAG;
            }
        }
        */

        private string pointRefPointIdref = String.Empty;
        public string PointRefPointIdref
        {
            get
            {
                return pointRefPointIdref;
            }
            set
            {
                pointRefPointIdref = value;
            }
        }

        public override void BuildXMLForSpatialSchema(soGeometry objMetry)
        {
            XmlNode curveNode = null;
            XmlNode orientationNode = null;
            XmlNode primitiveNode = null;
            XmlNode segmentNode = null;
            XmlNode lineStringNode = null;
            XmlNode interpolationNode = null;
            XmlNode controlPointNode = null;
            XmlNode pointArrayNode = null;
            XmlNode arrayColumnNode = null;
            XmlNode indirectNode = null;
            XmlNode pointRefNode = null;
            XmlNode pointRefPointNode = null;
            //soPoints tmpPoints = null;
            string curveId = String.Empty;

            //Node
            curveNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, CURVE_TAG, Utility.JPS_URI);
            orientationNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, ORIENTATION_TAG, Utility.JPS_URI);
            primitiveNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, PRIMITIVE_TAG, Utility.JPS_URI);
            segmentNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, SEGMENT_TAG, Utility.JPS_URI);
            lineStringNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, LINESTRING_TAG, Utility.JPS_URI);
            interpolationNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, INTERPOLATION_TAG, Utility.JPS_URI);
            controlPointNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, CONTROLPOINT_TAG, Utility.JPS_URI);
            pointArrayNode = XMLDoc.CreateElement(
                Utility.CM_JPS_TAG, POINTARRAY_TAG, Utility.JPS_URI);

            //CollectPart(objMetry as soGeoLine);

            //Attribute & Value
            soPoints tmpPoints = ((soGeoLine)objMetry).GetPartAt(1);
            curveId = Utility.curvePair[tmpPoints[1].x].ToString();
            (curveNode as XmlElement).SetAttribute(Utility.CM_ATTRIBUTE_ID_TAG, curveId);
            orientationNode.InnerText = ORIENTATION_VALUE;
            (primitiveNode as XmlElement).SetAttribute(
                Utility.CM_ATTRIBUTE_IDREF_TAG, 
                curveNode.Attributes[Utility.CM_ATTRIBUTE_ID_TAG].Value);
            interpolationNode.InnerText = INTERPOLATION_VALUE;

            //Append
            ObjectNode.AppendChild(curveNode);
            curveNode.AppendChild(orientationNode);
            curveNode.AppendChild(primitiveNode);
            primitiveNode.AppendChild(segmentNode);
            segmentNode.AppendChild(lineStringNode);
            lineStringNode.AppendChild(interpolationNode);
            lineStringNode.AppendChild(controlPointNode);
            controlPointNode.AppendChild(pointArrayNode);

            /*Point array*/
            //soPoints tmpPoints = ((soGeoLine)objMetry).GetPartAt(1);
            for (int i = 1; i <= tmpPoints.Count; i++)
            {
                Console.WriteLine("{0}, {1}, {2}", tmpPoints[i].x, curveId, i);
                if (Utility.pointsForCurve[tmpPoints[i].x].ToString() == curveId)
                {
                    //Node
                    arrayColumnNode = XMLDoc.CreateElement(ARRAYCOLUMN_TAG);
                    indirectNode = XMLDoc.CreateElement(
                        Utility.CM_JPS_TAG, INDIRECT_TAG, Utility.JPS_URI);
                    pointRefNode = XMLDoc.CreateElement(
                        Utility.CM_JPS_TAG, POINTREF_TAG, Utility.JPS_URI);
                    pointRefPointNode = XMLDoc.CreateElement(POINTREFPOINT_TAG);
                    //Attribute
                    (pointRefPointNode as XmlElement).SetAttribute(
                        Utility.CM_ATTRIBUTE_IDREF_TAG, Utility.pointPair[tmpPoints[i].x].ToString());
                    //Append
                    pointArrayNode.AppendChild(arrayColumnNode);
                    arrayColumnNode.AppendChild(indirectNode);
                    indirectNode.AppendChild(pointRefNode);
                    pointRefNode.AppendChild(pointRefPointNode);
                }
            }

            Utility.datasetCurve[curveId] = STRFeature;

            Marshal.ReleaseComObject(tmpPoints);
            tmpPoints = null;
        }

        public override void CollectPart(soGeometry objMetry)
        {
            soPoints tmpPoints = null;
            soGeoPoint objPoint = null;
            Point point = null;
            string curveId = String.Empty;

            objPoint = new soGeoPoint();
            tmpPoints = ((soGeoLine)objMetry).GetPartAt(1);
            curveId = ID_PREFIX + String.Format("{0, 0:D4}", ++Utility.idxCurve);
            for (int i = 1; i <= tmpPoints.Count; i++)
            {
                if (!Utility.pointsForCurve.Contains(tmpPoints[i]))
                {
                    Utility.pointsForCurve[tmpPoints[i].x] = curveId;
                    
                    objPoint.x = tmpPoints[i].x;
                    objPoint.y = tmpPoints[i].y;
                    point = new Point(XMLDoc, ObjectNode, curveId);
                    point.BuildXMLForSpatialSchema(objPoint as soGeometry);
                }
            }
            Utility.curvePair[tmpPoints[1].x] = curveId;

            Marshal.ReleaseComObject(tmpPoints);
            tmpPoints = null;
            Marshal.ReleaseComObject(objPoint);
            objPoint = null;
        }
    }
}
